package com.aterrizar.aerolinea;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.aterrizar.asiento.Asiento;
import com.aterrizar.exception.CompraNoRealizadaException;
import com.aterrizar.exception.ParametrosNulosException;
import com.aterrizar.exception.ReservaNoRealizadaException;
import com.aterrizar.sistema.Aterrizar;
import com.aterrizar.usuario.Usuario;
import com.oceanic.AerolineaOceanic;
import com.oceanic.AsientoDTO;

public class Oceanic implements Aerolinea {

	private static final Oceanic INSTANCE = new Oceanic();
	private Integer porcentaje;
	private Map<String, String> mapa_ciudades;
	private AerolineaOceanic aerolineaOceanic;
	private Map<String, String> mapa_ciudades_oceanic;
	
	private Oceanic() {
		this.aerolineaOceanic = AerolineaOceanic.getInstance();
		mapa_ciudades = new HashMap<String, String>();
		mapa_ciudades.put("La Rioja", "_LR");
		mapa_ciudades.put("Buenos Aires", "_BS");
		mapa_ciudades.put("Nueva York", "_NY");
		mapa_ciudades.put("Los Angeles", "SLA");
		mapa_ciudades.put("Ezeiza", "EZE");
		mapa_ciudades.put("Estados Unidos", "USA");
		mapa_ciudades.put("Peru", "PER");
		mapa_ciudades.put("Usuahia", "USH");
		mapa_ciudades.put("Aeroparque", "AEO");
		
		mapa_ciudades_oceanic = new HashMap<String, String>();
		mapa_ciudades_oceanic.put("_LR", "La Rioja");
		mapa_ciudades_oceanic.put("_BS", "Buenos Aires");
		mapa_ciudades_oceanic.put("_NY", "Nueva York");
		mapa_ciudades_oceanic.put("SLA", "Los Angeles");
		mapa_ciudades_oceanic.put("EZE", "Ezeiza");
		mapa_ciudades_oceanic.put("USA", "Estados Unidos");
		mapa_ciudades_oceanic.put("PER", "Peru");
		mapa_ciudades_oceanic.put("USH", "Usuahia");
		mapa_ciudades_oceanic.put("AEO", "Aeroparque");
	}

	public static void establecerPorcentaje(Integer porcentaje) {
		INSTANCE.setPorcentaje(porcentaje);
	}
	
	public static Oceanic getInstance() {
		return INSTANCE;
	}

	public Set<Asiento> buscar(Usuario usuario, String origen, String destino,
			String fechaDeSalida, String horaSalida, String horaLlegada) {

		Set<Asiento> asientosDisponibles = new HashSet<Asiento>();
		String origenOceanic;
		String destinoOceanic;
		
		if(origen!=null && destino!=null && fechaDeSalida!=null){
			origenOceanic = mapa_ciudades.get(origen);
			destinoOceanic = mapa_ciudades.get(destino);
			List<AsientoDTO> asientos = aerolineaOceanic.asientosDisponiblesParaOrigenYDestino(origenOceanic,
							destinoOceanic, fechaDeSalida);
			
			asientosDisponibles = asientosDTOToAsientos(usuario, asientos);
		}
		else
			throw new ParametrosNulosException();
		
		return asientosDisponibles;	
	}

	private Set<Asiento> asientosDTOToAsientos(Usuario usuario,
			List<AsientoDTO> asientos) {
		Set<Asiento> asientosDisponibles = new HashSet<Asiento>();
		for (AsientoDTO asiento : asientos) {
			if (asiento.getReservado() == false) {
				String numAsiento = String.valueOf(asiento.getNumeroDeAsiento().intValue());
				String codigo_asiento = asiento.getCodigoDeVuelo().concat("-").concat(numAsiento);
				BigDecimal recargo = usuario != null ? new BigDecimal(usuario.getTipoUsuario().getRecargo()) : new BigDecimal(0);
				Asiento nuevoAsiento = new Asiento(codigo_asiento,
												   asiento.getPrecio(), 
												   adaptarClase(asiento.getClase()),
												   adaptarUbicacion(asiento.getUbicacion()), 
												   asiento.getFechaDeSalida(),
												   asiento.getFechaDeLlegada(),
												   asiento.getHoraDeSalida(),
												   asiento.getHoraDeLlegada(), 
												   mapa_ciudades_oceanic.get(asiento.getOrigen()),
												   mapa_ciudades_oceanic.get(asiento.getDestino()),
												   this);
				BigDecimal uno = new BigDecimal(1);
				
				BigDecimal porcentajeAerolinea = ((new BigDecimal(this.getPorcentaje())).divide(new BigDecimal(100))).add(uno);
				
				nuevoAsiento.setPrecio(nuevoAsiento.getPrecio().multiply(porcentajeAerolinea).add(recargo));
				
				asientosDisponibles.add(nuevoAsiento);
			}
		}
		return asientosDisponibles;
	}

	public void comprar(String codigo, String dni) {
		boolean resultado_compra = aerolineaOceanic.comprarSiHayDisponibilidad(dni, codigo.split("-")[0],
						new Integer(codigo.split("-")[1]));
		if (resultado_compra == false) {
			throw new CompraNoRealizadaException();
		}
	}

	public void reservar(String codigo, String dni) {
		boolean resultado_reserva = aerolineaOceanic.reservar(
				dni, codigo.split("-")[0], new Integer(codigo.split("-")[1]));
		if (resultado_reserva == false) {
			throw new ReservaNoRealizadaException();
		}
	}

	public Integer getPorcentaje() {
		return porcentaje;
	}

	public void setPorcentaje(Integer porcentaje) {
		this.porcentaje = porcentaje;
	}

	public String adaptarClase(String clase) {
		if (clase.equalsIgnoreCase("Turista"))
			return TURISTA;
		if (clase.equalsIgnoreCase("Ejecutiva"))
			return EJECUTIVA;
		if (clase.equalsIgnoreCase("Primera"))
			return PRIMERA;
		return null;
	}

	public String adaptarUbicacion(String ubicacion) {
		if (ubicacion.equalsIgnoreCase("Ventana"))
			return VENTANA;
		if (ubicacion.equalsIgnoreCase("Pasillo"))
			return PASILLO;
		if (ubicacion.equalsIgnoreCase("Centro"))
			return CENTRO;
		return null;
	}
	
	
	public void actualizarReservasVencidas(List<AsientoDTO> listaDeAsientos) {
		Aterrizar.getInstance().removerCaducados(
				new ArrayList<Asiento>(asientosDTOToAsientos(null,
						listaDeAsientos)));
	}
	  public AerolineaOceanic getAerolineaOceanic() {
          return aerolineaOceanic;
  }

  public void setAerolineaOceanic(AerolineaOceanic aerolineaOceanic) {
          this.aerolineaOceanic = aerolineaOceanic;
  }
  
  @Override
	public String getNombre() {
		return this.getClass().getSimpleName();
	}
}